package com.anji.plus.gaea.annotation.resolver.mask;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.*;

import org.springframework.util.CollectionUtils;

import com.anji.plus.gaea.annotation.GaeaMask;
import com.anji.plus.gaea.bean.ResponseBean;
import com.anji.plus.gaea.utils.GaeaMaskUtils;

/**
 * 脱敏工具类
 * @author wangbin 
 **/
@Slf4j
public class MaskResolveUtil {

    /**
     * 脱敏数据
     *
     * @param obj
     * @return void
     */
    public static void resolve(Object obj,Field[] fieldArr) throws IllegalAccessException {
        if (null == obj) {
            return;
        }
        Object data = obj;
        Class<?> clazz = obj.getClass();
        //如果是通用的分页响应对象，则对该对象内部的List<T>进行脱敏
        if (obj.getClass().equals(ResponseBean.class)) {
            data = ((ResponseBean) obj).getData();
            clazz = data.getClass();
        }
        if (null == clazz) {
            return;
        }

        // 获取所有属性
        Field[] fields = null;
        if(fieldArr == null) {
            fields = getFields(clazz);
        }else {
            fields = fieldArr;
        }
        if (null == fields || fields.length == 0) {
            return;
        }

        for (Field field : fields) {
            if (null == field) {
                continue;
            }
            field.setAccessible(true);

            Class<?> t = field.getType();
            // 1.处理子属性，包括集合中的
            if (t.isArray()) {
                Object value = field.get(data);
                if(Objects.isNull(value)){
                    continue;
                }
                int len = Array.getLength(value);
                for (int i = 0; i < len; i++) {
                    Object arrayObject = Array.get(value, i);
                    if(Objects.isNull(arrayObject)){
                        continue;
                    }
                    if(i == 0){
                        fields = getFields(arrayObject.getClass());
                    }
                    MaskResolveUtil.resolve(arrayObject,fields);
                }
            } else if (Collection.class.isAssignableFrom(t)) {
                Object value = field.get(data);
                Collection<?> c = (Collection<?>) value;
                if(CollectionUtils.isEmpty(c)){
                    continue;
                }
                Iterator<?> it = c.iterator();
                boolean init = false;
                while (it.hasNext()) {
                    Object collectionObj = it.next();
                    if(!init) {
                        fields = getFields(collectionObj.getClass());
                        init = true;
                    }
                    MaskResolveUtil.resolve(collectionObj,fields);
                }
            } else if (Map.class.isAssignableFrom(t)) {
                Object value = field.get(data);
                if(Objects.isNull(value)){
                    continue;
                }
                Map<?, ?> m = (Map<?, ?>) value;
                Set<?> set = m.entrySet();
                for (Object o : set) {
                    Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
                    Object mapVal = entry.getValue();
                    MaskResolveUtil.resolve(mapVal,null);
                }
            }
            // 2. 处理自身的属性
            if (field.getType().equals(String.class)) {
                GaeaMask gaeaMask = field.getAnnotation(GaeaMask.class);
                if(Objects.isNull(gaeaMask)){
                    continue;
                }
                String value = (String) field.get(data);
                if(StringUtils.isEmpty(value)){
                    continue;
                }
                MaskEnum type = gaeaMask.type();
                String result = GaeaMaskUtils.getMaskValue(value,type,gaeaMask);
                if(!Objects.equals(result,value)){
                    field.set(data,result);
                }
            }
        }

    }

    public static Field[] getFields(Class clazz){
        if(clazz == null){
            return null;
        }
        Field[] fields = clazz.getDeclaredFields();
        while (null != clazz.getSuperclass() && !Object.class.equals(clazz.getSuperclass())) {
            fields = ArrayUtils.addAll(fields, clazz.getSuperclass().getDeclaredFields());
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

}

